home *** CD-ROM | disk | FTP | other *** search
/ Compendium Deluxe 1 / LSD Compendium Deluxe 1.iso / a / programming / misc / flxc101.lha / flexcat / src / FlexCat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-19  |  31.2 KB  |  1,540 lines

  1. /*
  2.     FlexCat.c:    The flexible catalog creator                V 1.01
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.  
  19.  
  20.     Ok, this is nothing special. It grabs a catalog translation and a
  21.     catalog description file and produces catalogs and the source to
  22.     handle 'em. What is it else than lots of other programs?
  23.  
  24.     The difference is, that YOU determine what source FlexCat produces.
  25.     Another file is scanned by FlexCat to produce code. This file contains
  26.     some c-string like special characters (%v for version for example)
  27.     You can edit this file and modify it as you want. So FlexCat can produce
  28.     C source as well as Assembler, Oberon, Modula 2, E, ...
  29.  
  30.     Command line syntax:
  31.  
  32.     FlexCat CDFILE/A,CTFILE,NEWCTFILE/K,CATALOG/K,ASSEMBLER/S,SOURCES/M
  33.  
  34.     CDFILE    - the name of the catalog description file; see CatComp for
  35.         syntax
  36.     CTFILE    - the name of a catalog translation file; see CatComp for
  37.         syntax
  38.     NEWCTFILE - the name of a catalog transcription file to be created
  39.         (will be a copy of CDFILE except that the strings remain
  40.         empty and will be put as comments behind the string
  41.         definition)
  42.     CATALOG   - the name of the catalog to be created; default is the
  43.         basename of the CDFILE and .catalog appended
  44.     SOURCES   - the sourcefiles to be created. These arguments take a special
  45.         form: sourcefile=templatefile where sourcefile is the
  46.         name of the file to create and templatefile is the name of
  47.         a template file containing some special patterns. The
  48.         template file will be scanned and written to the source
  49.         file with these special patterns replaced by certain
  50.         strings. Possible patterns are:
  51.  
  52.             %b        basename of CDFILE (for example "file", if
  53.                 CDFILE is "file.cd")
  54.             %v        version
  55.             %l        language (of CDFILE)
  56.             %n        number of catalog strings
  57.             %%        the percent sign itself
  58.  
  59.         The following patterns indicate, that the line should be
  60.         repeated for each catalog string.
  61.             %i        the string's ID descriptor
  62.             %d        the string's ID
  63.             %s        the string itself
  64.             %(...)  indicates that anything between the brackets
  65.                 should appear for any line except the last
  66.                 (Oberon and Modula need a "," to separate array
  67.                 entries, but the last entry must not be
  68.                 terminated by a ",". So you would terminate an
  69.                 array entry by a %(,).)
  70.  
  71.     Example: Let the string description be
  72.  
  73.     MSG_HELLO (5//)
  74.     Hello!
  75.  
  76.     Then the special characters produce
  77.     %i = MSG_HELLO
  78.     %d = 5
  79.     %s = "Hello!"
  80.  
  81.     Additionally the following characters may appear (as well as in the
  82.     catalog description and catalog translation file)
  83.     \b    = Backspace (Ascii 8)
  84.     \c    = Control sequence introducer (Ascii 155)
  85.     \e    = Escape (Ascii 27)
  86.     \f    = Form feed (Ascii 12)
  87.     \g    = Display beep (Ascii 7)
  88.     \n    = line feed, newline (Ascii 10)
  89.     \r    = carriage return (Ascii 13)
  90.     \t    = Tab (Ascii 9)
  91.     \v    = Vertical tab (Ascii 11)
  92.     \)    = the character ')' (Needed inside %(..))
  93.     \\    = the backslash itself
  94.     \xHH  = Ascii code HH (where HH are hex digits)
  95.     \OOO  = Ascii code OOO (where OOO are octal digits)
  96.  
  97.     A backslash at the end of a line indicates that the line should be
  98.     concatenated with the next one.
  99.  
  100.  
  101.     Computer:    Amiga 1200            Compiler: Dice, 2.07.54R
  102.  
  103.     Author:    V 1.0        31.06.1993        Jochen Wiedmann
  104.                         Am Eisteich 9
  105.                       72555 Metzingen
  106.                         Tel. 07123 / 14881
  107.  
  108.                 Internet: wiedmann@mailserv.zdv.uni-tuebingen.de
  109.  
  110.         V1.01        Fixed a bug: The length of the source string
  111.                 was used to check for the stringlen instead of
  112.                 the real stringlen.
  113. */
  114.  
  115.  
  116.  
  117. #include <stdlib.h>
  118. #include <stdio.h>
  119. #include <string.h>
  120. #include <ctype.h>
  121. #ifdef AMIGA
  122. #include <exec/types.h>
  123. #include <clib/exec_protos.h>
  124. #include "FlexCat_cat.h"
  125. #ifdef AZTEC_C
  126. #include <pragmas/exec_lib.h>
  127. #endif
  128. #endif
  129.  
  130. #ifdef _DCC
  131. #define index strchr
  132. #define rindex strrchr
  133. #endif
  134.  
  135. #ifndef FALSE
  136. #define FALSE 0
  137. #endif
  138. #ifndef TRUE
  139. #define TRUE (!FALSE)
  140. #endif
  141.  
  142.  
  143. #define TYPE_C         0  /*    Produce C strings            */
  144. #define TYPE_ASSEMBLER     1  /*    Produce Assembler strings        */
  145. #define TYPE_OBERON     2  /*    Produce Oberon strings            */
  146. #define TYPE_NONE     3  /*    Simple strings                */
  147.  
  148. #define OutputMode_None  0  /*    Nothing written yet            */
  149. #define OutputMode_Bin     1  /*    Last character written was binary   */
  150. #define OutputMode_Ascii 2  /*    Last character written was Ascii    */
  151.  
  152. struct CatString
  153. { struct CatString *Next;
  154.   char *CD_Str;
  155.   char *CT_Str;
  156.   char *ID_Str;
  157.   int MinLen, MaxLen, ID;
  158. };
  159.  
  160. struct CDLine
  161. { struct CDLine *Next;
  162.   char *Line;
  163. };
  164.  
  165.  
  166. struct CatString *FirstCatString = NULL;  /*  First catalog string    */
  167. struct CDLine *FirstCDLine = NULL;  /*    First catalog description line    */
  168.  
  169. char *BaseName = "";                /*  Basename of catalog description */
  170. char *Language = "english";         /*  Language of catalog description */
  171. int CatVersion = 0;            /*    Version of catalog to be opened */
  172. int LengthBytes = 0;            /*    Number of bytes to preceed a    */
  173.                     /*    created string and containing    */
  174.                     /*    its length.            */
  175. char *CatLanguage = NULL;        /*    Language of catalog translation */
  176. char *CatVersionString = NULL;        /*    version string of catalog    */
  177.                     /*    translation            */
  178. int CodeSet = 0;            /*    Codeset of catalog translation    */
  179. int NumStrings = 0;            /*    Number of catalog strings    */
  180. int LongStrings = TRUE;         /*    Generate long or short strings    */
  181.  
  182.  
  183. char *ScanFile;             /*    File currently scanned        */
  184. int ScanLine;                /*    Line currently scanned        */
  185.  
  186. struct Library *LocaleBase = NULL;
  187.  
  188.  
  189.  
  190. /*
  191.     This terminates the program.
  192. */
  193. void Cleanup(int result)
  194.  
  195. {
  196. #ifdef AMIGA
  197.   CloseFlexCatCatalog();
  198.   if (LocaleBase)
  199.   { CloseLibrary(LocaleBase);
  200.   }
  201. #endif
  202.   exit(result);
  203. }
  204.  
  205. /*
  206.     This shows an error message and terminates
  207. */
  208. struct RDArgs *Args;
  209. void ShowError(const STRPTR msg, ...)
  210.  
  211. { fprintf(stderr, (char *) msg, (&msg)[1], (&msg)[2], (&msg)[3], (&msg)[4]);
  212.   putc('\n', stderr);
  213.   Cleanup(10);
  214. }
  215.  
  216.  
  217.  
  218. /*
  219.     This shows the message: Memory error.
  220. */
  221. void MemError(void)
  222.  
  223. { ShowError(GetFlexCatString(msgMemoryError), NULL);
  224. }
  225.  
  226.  
  227.  
  228.  
  229. /*
  230.     This shows a warning
  231. */
  232. void ShowWarn(STRPTR msg, ...)
  233.  
  234. { fprintf(stderr, (char *) GetFlexCatString(msgWarning), ScanFile, ScanLine);
  235.   fprintf(stderr, (char *) msg, (&msg)[1], (&msg)[2], (&msg)[3], (&msg)[4]);
  236.   putc('\n', stderr);
  237. }
  238.  
  239.  
  240.  
  241.  
  242. /*
  243.     This allocates a string
  244. */
  245. char *AllocString(const char *str)
  246.  
  247. { char *ptr;
  248.  
  249.   if (!(ptr = malloc(strlen(str)+1)))
  250.   { MemError();
  251.   }
  252.   strcpy(ptr, str);
  253.   return(ptr);
  254. }
  255.  
  256.  
  257.  
  258.  
  259. /*
  260.     This translates a hex character.
  261. */
  262. int gethex(int c)
  263.  
  264. {
  265.   if (c >= '0'  &&  c <= '9')
  266.   { return(c - '0');
  267.   }
  268.   else if (c >= 'a'  &&  c <= 'f')
  269.   { return(c - 'a' + 10);
  270.   }
  271.   else if (c >= 'A'  &&  c <= 'F')
  272.   { return(c - 'A' + 10);
  273.   }
  274.   ShowWarn(GetFlexCatString(msgExpectedHex));
  275.   return(0);
  276. }
  277.  
  278.  
  279.  
  280.  
  281. /*
  282.     This translates an octal digit.
  283. */
  284. int getoctal(int c)
  285.  
  286. {
  287.   if (c >= '0'  &&  c <= '7')
  288.   { return(c - '0');
  289.   }
  290.   ShowWarn(GetFlexCatString(msgExpectedOctal));
  291.   return(0);
  292. }
  293.  
  294.  
  295.  
  296.  
  297. /*
  298.     Reading a line is somewhat compicated in order to allow lines of any
  299.     length.
  300.  
  301.     Inputs: fp         - the file, where the input comes from
  302.         AllowComment - TRUE, if a leading semicolon should force to
  303.                interpret the line as a comment line
  304. */
  305. #define BUFSIZE 4096
  306. char *ReadLine(FILE *fp, int AllowComment)
  307.  
  308. { char *OldLine, *NewLine = NULL;
  309.   int c = '\0';
  310.   int Len = 0, LineLen = 0;
  311.   int CommentLine = FALSE, FirstChar = TRUE;
  312.   int BackslashSeen = FALSE;
  313.  
  314.   while (c != EOF)
  315.   { if (Len+10 > LineLen)
  316.     { OldLine = NewLine;
  317.       if (!(NewLine = malloc(LineLen+BUFSIZE)))
  318.       { MemError();
  319.       }
  320.       strncpy(NewLine, OldLine, LineLen);
  321.       if (OldLine)
  322.       { free(OldLine);
  323.       }
  324.       LineLen += BUFSIZE;
  325.     }
  326.  
  327.     c = getc(fp);
  328.     if (FirstChar)
  329.     { if (c == ';')
  330.       { CommentLine = TRUE;
  331.       }
  332.       if (c == EOF)
  333.       { free(NewLine);
  334.     return(NULL);
  335.       }
  336.       FirstChar = FALSE;
  337.     }
  338.  
  339.     switch(c)
  340.     { case '\r':
  341.     break;
  342.       case '\n':
  343.     ++ScanLine;
  344.     if (BackslashSeen)
  345.     { NewLine[Len++] = c;
  346.       BackslashSeen = FALSE;
  347.       break;
  348.     }
  349.     c = EOF;
  350.       case EOF:
  351.     break;
  352.       case '\\':
  353.     BackslashSeen = TRUE;
  354.     NewLine[Len++] = c;
  355.     break;
  356.       default:
  357.     BackslashSeen = FALSE;
  358.     NewLine[Len++] = c;
  359.     }
  360.   }
  361.   NewLine[Len++] = '\0';
  362.  
  363.   return(NewLine);
  364. }
  365.  
  366.  
  367.  
  368.  
  369. /*
  370.     This removes trailing blanks.
  371. */
  372. void OverSpace(char **strptr)
  373.  
  374. { int c;
  375.  
  376.   while ((c = **strptr) == ' '  ||  c == '\t')
  377.   { (*strptr)++;
  378.   }
  379. }
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388. /*
  389.     ReadChar scans an input line translating the backslash characters.
  390.  
  391.     Inputs: strptr  - a pointer to a stringpointer; the latter points to the
  392.               next character to be read and points behind the read
  393.               bytes after executing ReadChar
  394.         dest    - a pointer to a buffer, where the read bytes should be
  395.               stored
  396.  
  397.     Result: number of bytes that are written to dest (between 0 and 2)
  398. */
  399. int ReadChar(char **strptr, char *dest)
  400.  
  401. { char c;
  402.   int i;
  403.  
  404.   switch(c = *((*strptr)++))
  405.   { case '\\':
  406.       switch(c = tolower((int) *((*strptr)++)))
  407.       { case '\n':
  408.       return(0);
  409.     case 'b':
  410.       *dest = '\b';
  411.       break;
  412.     case 'c':
  413.       *dest = '\233';
  414.       break;
  415.     case 'e':
  416.       *dest = '\033';
  417.       break;
  418.     case 'f':
  419.       *dest = '\f';
  420.       break;
  421.     case 'g':
  422.       *dest = '\007';
  423.       break;
  424.     case 'n':
  425.       *dest = '\n';
  426.       break;
  427.     case 'r':
  428.       *dest = '\r';
  429.       break;
  430.     case 't':
  431.       *dest = '\t';
  432.       break;
  433.     case 'v':
  434.       *dest = '\013';
  435.       break;
  436.     case 'x':
  437.       *dest = gethex((int) **strptr);
  438.       (*strptr)++;
  439.       if (((c = **strptr) >= '0'  &&  c <= '9')  ||
  440.           (c >= 'a'  &&  c <= 'f')  ||  (c >= 'A'  &&  c <= 'F'))
  441.       { *dest = (*dest << 4) + gethex((int) c);
  442.         (*strptr)++;
  443.       }
  444.       break;
  445.     case '0':
  446.     case '1':
  447.     case '2':
  448.     case '3':
  449.     case '4':
  450.     case '5':
  451.     case '6':
  452.     case '7':
  453.       *dest = getoctal((int) **strptr);
  454.       (*strptr)++;
  455.       for (i = 0;  i < 2;  i++)
  456.       { if ((c = **strptr) >= '0'  &&  c <= '7')
  457.         { *dest = (*dest << 3) + getoctal((int) c);
  458.           (*strptr)++;
  459.         }
  460.       }
  461.       break;
  462.     case ')':
  463.     case '\\':
  464.       *(dest++) = '\\';
  465.       *dest = c;
  466.       return(2);
  467.     default:
  468.       *dest = c;
  469.       }
  470.       break;
  471.     default:
  472.       *dest = c;
  473.   }
  474.   return(1);
  475. }
  476.  
  477.  
  478.  
  479.  
  480. /*
  481.     This scans the catalog description file.
  482.  
  483.     Inputs: cdfile  - name of the catalog description file
  484.  
  485.     Result: TRUE, if successfull, FALSE otherwise
  486. */
  487. int ScanCDFile(char *cdfile)
  488.  
  489. { FILE *fp;
  490.   struct CDLine *cdline, **cdptr = &FirstCDLine;
  491.   struct CatString *cs, **csptr = &FirstCatString;
  492.   char *line, *newline;
  493.   char *ptr;
  494.   int NextID = 0, len;
  495.   int Result = TRUE;
  496.  
  497.   ScanFile = cdfile;
  498.   ScanLine = 0;
  499.  
  500.   if (!(fp = fopen(cdfile, "r")))
  501.   { ShowError(GetFlexCatString(msgNoCatalogDescription), cdfile);
  502.   }
  503.  
  504.   /*
  505.       Get the basename
  506.   */
  507.   if (ptr = strchr(cdfile, ':'))
  508.   { cdfile = ptr;
  509.   }
  510.   if (ptr = strrchr(cdfile, '/'))
  511.   { cdfile = ptr+1;
  512.   }
  513.   if (ptr = strrchr(cdfile, '.'))
  514.   { len = ptr-cdfile;
  515.   }
  516.   else
  517.   { len = strlen(cdfile);
  518.   }
  519.   if (!(BaseName = malloc(len+1)))
  520.   { MemError();
  521.   }
  522.   strncpy(BaseName, cdfile, len);
  523.   BaseName[len] = '\0';
  524.  
  525.   while(!feof(fp)  &&  (line = newline = ReadLine(fp, TRUE)))
  526.   { if (!(cdline = malloc(sizeof(*cdline))))
  527.     { MemError();
  528.     }
  529.     *cdptr = cdline;
  530.     cdptr = &cdline->Next;
  531.     cdline->Next = NULL;
  532.     cdline->Line = line = AllocString(newline);
  533.     free(newline);
  534.  
  535.     if (*line == ';')
  536.     { continue;
  537.     }
  538.     if (*line == '#')
  539.     { int CheckExtra = TRUE;
  540.  
  541.       if (strnicmp(line+1, "language", 8) == 0)
  542.       { char *ptr;
  543.  
  544.     line += 9;
  545.     OverSpace(&line);
  546.     Language = AllocString(line);
  547.     for (ptr = Language;  *ptr;  ptr++)
  548.     { *ptr = tolower((int) *ptr);
  549.     }
  550.     CheckExtra = FALSE;
  551.       }
  552.       else if (strnicmp(line+1, "version", 7) == 0)
  553.       { CatVersion = strtol(line+8, &line, 10);
  554.       }
  555.       else if (strnicmp(line+1, "lengthbytes", 11) == 0)
  556.       { line += 12;
  557.     if ((LengthBytes = strtol(line, &line, 10))
  558.              > sizeof(long))
  559.     { ShowWarn(GetFlexCatString(msgNoLengthBytes), sizeof(long));
  560.       LengthBytes = sizeof(long);
  561.     }
  562.       }
  563.       else if (strnicmp(line+1, "basename", 8) == 0)
  564.       { line += 9;
  565.     OverSpace(&line);
  566.     free(BaseName);
  567.     BaseName = AllocString(line);
  568.     CheckExtra = FALSE;
  569.       }
  570.       else
  571.       { ShowWarn(GetFlexCatString(msgUnknownCDCommand));
  572.     Result = FALSE;
  573.     CheckExtra = FALSE;
  574.       }
  575.       if (CheckExtra)
  576.       { OverSpace(&line);
  577.     if (*line)
  578.     { ShowWarn(GetFlexCatString(msgExtraCharacters));
  579.       Result = FALSE;
  580.     }
  581.       }
  582.     }
  583.     else
  584.     { char *idstr;
  585.  
  586.       if (*line == ' '  ||  *line == '\t')
  587.       { ShowWarn(GetFlexCatString(msgUnexpectedBlanks));
  588.     Result = FALSE;
  589.     OverSpace(&line);
  590.       }
  591.  
  592.       idstr = line;
  593.       while ((*line >= 'a'  &&  *line <= 'z')  ||
  594.          (*line >= 'A'  &&  *line <= 'Z')  ||
  595.          (*line >= '0'  &&  *line <= '9')  ||
  596.          *line == '_')
  597.       { ++line;
  598.       }
  599.  
  600.       if (idstr == line)
  601.       { ShowWarn(GetFlexCatString(msgNoIdentifier));
  602.     Result = FALSE;
  603.       }
  604.       else
  605.       { int found;
  606.  
  607.     if (!(cs = malloc(sizeof(*cs))))
  608.     { MemError();
  609.     }
  610.  
  611.     do
  612.     { struct CatString *scs;
  613.  
  614.       found = TRUE;
  615.       for (scs = FirstCatString;  scs != NULL;  scs = scs->Next)
  616.       { if (scs->ID == NextID)
  617.         { found = FALSE;
  618.           ++NextID;
  619.           break;
  620.         }
  621.       }
  622.     }
  623.     while (!found);
  624.  
  625.     cs->Next = NULL;
  626.     cs->ID = NextID;
  627.     cs->MinLen = 0;
  628.     cs->MaxLen = -1;
  629.     cs->CD_Str = "";
  630.     cs->CT_Str = NULL;
  631.  
  632.     if (!(cs->ID_Str = malloc((line-idstr)+1)))
  633.     { MemError();
  634.     }
  635.     strncpy(cs->ID_Str, idstr, line-idstr);
  636.     cs->ID_Str[line-idstr] = '\0';
  637.  
  638.     OverSpace(&line);
  639.  
  640.     if (*line != '(')
  641.     { ShowWarn(GetFlexCatString(msgNoLeadingBracket));
  642.       Result = FALSE;
  643.     }
  644.     else
  645.     { char *oldstr;
  646.       char bytes[10];
  647.       int bytesread, reallen;
  648.  
  649.       ++line;
  650.       OverSpace(&line);
  651.       if (*line != '/')
  652.       { struct CatString *scs;
  653.  
  654.         cs->ID = NextID = strtol(line, &line, 10);
  655.         for(scs = FirstCatString;  scs != NULL;  scs = scs->Next)
  656.         { if (scs->ID == cs->ID)
  657.           { ShowWarn(GetFlexCatString(msgDoubleID));
  658.         Result = FALSE;
  659.           }
  660.           if (strcmp(cs->ID_Str, scs->ID_Str)  ==  0)
  661.           { ShowWarn(GetFlexCatString(msgDoubleIdentifier));
  662.         Result = FALSE;
  663.           }
  664.         }
  665.         OverSpace(&line);
  666.       }
  667.       if (*line != '/')
  668.       { ShowWarn(GetFlexCatString(msgNoMinLen));
  669.         Result = FALSE;
  670.       }
  671.       else
  672.       { ++line;
  673.         OverSpace(&line);
  674.         if (*line != '/')
  675.         { cs->MinLen = strtol(line, &line, 10);
  676.           OverSpace(&line);
  677.         }
  678.         if (*line != '/')
  679.         { ShowWarn(GetFlexCatString(msgNoMaxLen));
  680.           Result = FALSE;
  681.         }
  682.         else
  683.         { ++line;
  684.           OverSpace(&line);
  685.           if (*line != ')')
  686.           { cs->MaxLen = strtol(line, &line, 10);
  687.         OverSpace(&line);
  688.           }
  689.           if (*line != ')')
  690.           { ShowWarn(GetFlexCatString(msgNoTrailingBracket));
  691.         Result = FALSE;
  692.           }
  693.           else
  694.           { ++line;
  695.         OverSpace(&line);
  696.         if (*line)
  697.         { ShowWarn(GetFlexCatString(msgExtraCharacters));
  698.         }
  699.           }
  700.         }
  701.       }
  702.     if (!(newline = ReadLine(fp, FALSE)))
  703.     { ShowWarn(GetFlexCatString(msgNoString));
  704.       Result = FALSE;
  705.       cs->CD_Str = "";
  706.     }
  707.     else
  708.     { cs->CD_Str = AllocString(newline);
  709.       free(newline);
  710.     }
  711.  
  712.     /*
  713.         Get stringlen
  714.     */
  715.     oldstr = cs->CD_Str;
  716.     reallen = 0;
  717.     while (*oldstr)
  718.     { bytesread = ReadChar(&oldstr, bytes);
  719.       if (bytesread == 2)
  720.       { bytesread--;
  721.       }
  722.       reallen += bytesread;
  723.     }
  724.  
  725.     if (cs->MinLen > 0  &&  reallen < cs->MinLen)
  726.     { ShowWarn(GetFlexCatString(msgShortString));
  727.     }
  728.     if (cs->MaxLen > 0  &&  reallen > cs->MaxLen)
  729.     { ShowWarn(GetFlexCatString(msgLongString));
  730.     }
  731.  
  732.     *csptr = cs;
  733.     csptr = &cs->Next;
  734.     ++NumStrings;
  735.     }
  736.       }
  737.     }
  738.   }
  739.   fclose(fp);
  740.   return(Result);
  741. }
  742.  
  743.  
  744.  
  745.  
  746. /*
  747.     This scans a catalog translation file.
  748.  
  749.     Inputs: ctfile    - name of the translation file to scan.
  750.         CreateNew    - TRUE, if a new translation file should be created.
  751.  
  752.     Result: TRUE, if successfull, FALSE otherwise.
  753. */
  754. int ScanCTFile(char *ctfile, int CreateNew)
  755.  
  756. { FILE *fp;
  757.   char *newline, *line, *idstr, *newidstr, *newstr;
  758.   struct CatString *cs;
  759.   int Result = TRUE;
  760.  
  761.   ScanFile = ctfile;
  762.   ScanLine = 0;
  763.  
  764.   if (!(fp = fopen(ctfile, "r")))
  765.   { ShowError(GetFlexCatString(msgNoCatalogTranslation), ctfile);
  766.   }
  767.  
  768.  
  769.   while (!feof(fp)  &&  (line = newline = ReadLine(fp, TRUE)))
  770.   { switch(*line)
  771.     { case ';':
  772.     break;
  773.       case '#':
  774.     if (*(++line) != '#')
  775.     { ShowWarn(GetFlexCatString(msgNoCTCommand));
  776.     }
  777.     ++line;
  778.     OverSpace(&line);
  779.     if (strnicmp(line, "version", 7) == 0)
  780.     { line += 7;
  781.       OverSpace(&line);
  782.       CatVersionString = AllocString(line);
  783.     }
  784.     else if (strnicmp(line, "codeset", 7) == 0)
  785.     { line += 7;
  786.       CodeSet = strtol(line, &line, 10);
  787.       OverSpace(&line);
  788.       if (*line)
  789.       { ShowWarn(GetFlexCatString(msgExtraCharacters));
  790.       }
  791.     }
  792.     else if (strnicmp(line, "language", 8) == 0)
  793.     { char *ptr;
  794.  
  795.       line += 8;
  796.       OverSpace(&line);
  797.       CatLanguage = AllocString(line);
  798.       for (ptr = CatLanguage;  *ptr;  ptr++)
  799.       { *ptr = tolower((int) *ptr);
  800.       }
  801.     }
  802.     else
  803.     { ShowWarn(GetFlexCatString(msgUnknownCTCommand));
  804.     }
  805.     break;
  806.       default:
  807.     if (*line == ' '  ||  *line == '\t')
  808.     { ShowWarn(GetFlexCatString(msgUnexpectedBlanks));
  809.       OverSpace(&line);
  810.     }
  811.     idstr = line;
  812.     while ((*line >= 'a'  &&  *line <= 'z')  ||
  813.            (*line >= 'A'  &&  *line <= 'Z')  ||
  814.            (*line >= '0'  &&  *line <= '9')  ||
  815.            *line == '_')
  816.     { ++line;
  817.     }
  818.     if (idstr == line)
  819.     { ShowWarn(GetFlexCatString(msgNoIdentifier));
  820.       break;
  821.     }
  822.     if (!(newidstr = malloc(line-idstr+1)))
  823.     { MemError();
  824.     }
  825.     strncpy(newidstr, idstr, line-idstr);
  826.     newidstr[line-idstr] = '\0';
  827.     OverSpace(&line);
  828.     if (*line)
  829.     { ShowWarn(GetFlexCatString(msgExtraCharacters));
  830.     }
  831.     if (!(newstr = ReadLine(fp, FALSE)))
  832.     { ShowWarn(GetFlexCatString(msgNoString));
  833.       cs->CT_Str = "";
  834.     }
  835.     else
  836.     { for(cs = FirstCatString;  cs != NULL;  cs = cs->Next)
  837.       { if (strcmp(cs->ID_Str, newidstr) == 0)
  838.         { break;
  839.         }
  840.       }
  841.       if (cs == NULL  &&  !CreateNew)
  842.       { ShowWarn(GetFlexCatString(msgUnknownIdentifier), newidstr);
  843.       }
  844.       else
  845.       { char *oldstr;
  846.         char bytes[10];
  847.         int bytesread, reallen;
  848.  
  849.         if (cs->CT_Str)
  850.         { ShowWarn(GetFlexCatString(msgDoubleIdentifier));
  851.           Result = FALSE;
  852.           free (cs->CT_Str);
  853.         }
  854.         cs->CT_Str = AllocString(newstr);
  855.  
  856.         /*
  857.         Get stringlen
  858.         */
  859.         oldstr = cs->CT_Str;
  860.         reallen = 0;
  861.         while (*oldstr)
  862.         { bytesread = ReadChar(&oldstr, bytes);
  863.           if (bytesread == 2)
  864.           { bytesread--;
  865.           }
  866.           reallen += bytesread;
  867.         }
  868.  
  869.         if (cs->MinLen > 0  &&  reallen < cs->MinLen)
  870.         { ShowWarn(GetFlexCatString(msgShortString));
  871.         }
  872.         if (cs->MaxLen > 0  &&  reallen > cs->MaxLen)
  873.         { ShowWarn(GetFlexCatString(msgLongString));
  874.         }
  875.       }
  876.       free(newstr);
  877.     }
  878.     free(newidstr);
  879.     }
  880.     free(newline);
  881.   }
  882.  
  883.   fclose(fp);
  884.   return(Result);
  885. }
  886. /*
  887.     CatPuts prints a string to a catalog. (The string is preceded by a
  888.     long integer containing its length and probably padded up to word
  889.     boundary or longword boundary, depending on the argument padbytes.)
  890. */
  891. int CatPuts(FILE *fp, char *str, int padbytes)
  892.  
  893. { unsigned long reallen, virtuallen, chunklen;
  894.   int bytesread;
  895.   char *oldstr;
  896.   char bytes[10];
  897.  
  898.   /*
  899.       Get Length of string.
  900.   */
  901.   oldstr = str;
  902.   reallen = 0;
  903.   while (*oldstr)
  904.   { bytesread = ReadChar(&oldstr, bytes);
  905.     if (bytesread == 2)
  906.     { bytesread--;
  907.     }
  908.     reallen += bytesread;
  909.   }
  910.   chunklen = reallen + LengthBytes;
  911.   if (((virtuallen = chunklen) % 4) == 0)
  912.   { virtuallen++;
  913.   }
  914.  
  915.   fwrite(&virtuallen, sizeof(virtuallen), 1, fp);
  916.   if (LengthBytes)
  917.   { fwrite(((char *) &reallen)+sizeof(reallen)-LengthBytes,
  918.        LengthBytes, 1, fp);
  919.   }
  920.   while(*str)
  921.   { bytesread = ReadChar(&str, bytes);
  922.     if (bytesread)
  923.     { fwrite(bytes+bytesread-1, 1, 1, fp);
  924.     }
  925.   }
  926.  
  927.   do
  928.   { putc('\0', fp);
  929.   }
  930.   while(++chunklen % padbytes);
  931.  
  932.   return(chunklen+4);
  933. }
  934.  
  935.  
  936.  
  937.  
  938. /*
  939.     This creates a catalog.
  940. */
  941. void CreateCat(char *CatFile)
  942.  
  943. { FILE *fp;
  944.   int Result = TRUE;
  945.   int CatLen, HeadLen;
  946.   struct CatString *cs;
  947.   int i;
  948.  
  949.   if (!CatVersionString)
  950.   { ShowError(GetFlexCatString(msgNoCTVersion));
  951.   }
  952.   if (!CatLanguage)
  953.   { ShowError(GetFlexCatString(msgNoCTLanguage));
  954.   }
  955.  
  956.   if (!(fp = fopen(CatFile, "w")))
  957.   { ShowError(GetFlexCatString(msgNoCatalog), CatFile);
  958.   }
  959.  
  960.   fputs("FORM0000CTLGFVER", fp);
  961.   CatLen = 8 + CatPuts(fp, CatVersionString, 2);
  962.   fputs("LANG", fp);
  963.   CatLen += 4 + CatPuts(fp, CatLanguage, 2);
  964.   fputs("CSET", fp);
  965.   i = 32;
  966.   fwrite(&i, sizeof(i), 1, fp);
  967.   while(i-- > 0)
  968.   { putc('\0', fp);
  969.   }
  970.   CatLen += 48;
  971.   fprintf(fp, "STRS0000");
  972.   HeadLen = CatLen;
  973.  
  974.   for (cs = FirstCatString;  cs != NULL;  cs = cs->Next)
  975.   { if (strcmp(cs->CT_Str, cs->CD_Str))
  976.     { fwrite(&cs->ID, sizeof(cs->ID), 1, fp);
  977.       CatLen += 4 + CatPuts(fp, cs->CT_Str, 4);
  978.     }
  979.   }
  980.  
  981.   fseek(fp, 4, SEEK_SET);
  982.   fwrite(&CatLen, sizeof(CatLen), 1, fp);
  983.   fseek(fp, HeadLen-4, SEEK_CUR);
  984.   CatLen -= HeadLen;
  985.   fwrite(&CatLen, sizeof(CatLen), 1, fp);
  986.   fclose(fp);
  987. }
  988.  
  989.  
  990.  
  991.  
  992. /*
  993.     This creates a new catalog translation file.
  994. */
  995. void CreateCTFile(char *NewCTFile)
  996.  
  997. { FILE *fp;
  998.   struct CDLine *cd;
  999.   struct CatString *cs;
  1000.   char *line;
  1001.  
  1002.   if (!(fp = fopen(NewCTFile, "w")))
  1003.   { ShowError(GetFlexCatString(msgNoNewCTFile));
  1004.   }
  1005.  
  1006.   fprintf(fp, "## version %s\n## language %s\n## codeset %d\n",
  1007.       CatVersionString, CatLanguage, CodeSet);
  1008.  
  1009.   for(cd = FirstCDLine, cs = FirstCatString;
  1010.       cd != NULL;
  1011.       cd = cd->Next)
  1012.   { switch(*cd->Line)
  1013.     { case '#':
  1014.     break;
  1015.       case ';':
  1016.     fprintf(fp, "%s\n", cd->Line);
  1017.     break;
  1018.       default:
  1019.     if(cs)
  1020.     { fprintf(fp, "%s\n", cs->ID_Str);
  1021.       fprintf(fp, "%s\n", cs->CT_Str ? cs->CT_Str : "");
  1022.       putc(';', fp);
  1023.       for (line = cs->CD_Str;  *line;  ++line)
  1024.       { putc((int) *line, fp);
  1025.         if(*line == '\n')
  1026.         { putc(';', fp);
  1027.         }
  1028.       }
  1029.       putc('\n', fp);
  1030.       cs = cs->Next;
  1031.     }
  1032.     }
  1033.   }
  1034.  
  1035.   fclose(fp);
  1036. }
  1037.  
  1038.  
  1039.  
  1040.  
  1041. /*
  1042.     InitCatStringOutput gets called before writing a catalog string as
  1043.     source.
  1044.  
  1045.     Inputs: fp     = file pointer to the output file
  1046.         type = one of   TYPE_C        create C strings
  1047.                 TYPE_ASSEMBLER  create Assembler strings
  1048.                 TYPE_OBERON     create Oberon strings
  1049.                 TYPE_NONE        create simple strings
  1050. */
  1051. int OutputMode = OutputMode_None;
  1052. int OutputType = TYPE_C;
  1053. FILE *OutputFile;
  1054. int OutputLen;
  1055. void InitCatStringOutput(FILE *fp)
  1056.  
  1057. {
  1058.   OutputLen = 0;
  1059.   OutputFile = fp;
  1060.   OutputMode = OutputMode_None;
  1061.   switch(OutputType)
  1062.   { case TYPE_C:
  1063.     case TYPE_OBERON:
  1064.       putc('\"', fp);
  1065.       OutputMode = OutputMode_Ascii;
  1066.       break;
  1067.     case TYPE_ASSEMBLER:
  1068.     case TYPE_NONE:
  1069.       break;
  1070.   }
  1071. }
  1072.  
  1073.  
  1074.  
  1075. /*
  1076.     SeparateCatStringOutput gets called to split a catalog into separate
  1077.     lines.
  1078. */
  1079. void SeparateCatStringOutput(void)
  1080.  
  1081. {
  1082.     switch(OutputType)
  1083.     { case TYPE_C:
  1084.     if (!LongStrings)
  1085.     { fputs("\"\\\n\t\"", OutputFile);
  1086.     }
  1087.     break;
  1088.       case TYPE_OBERON:
  1089.     if (!LongStrings)
  1090.     { fputs("\"\n\t\"", OutputFile);
  1091.     }
  1092.     break;
  1093.       case TYPE_ASSEMBLER:
  1094.     if (!LongStrings)
  1095.     { if (OutputMode == OutputMode_Ascii)
  1096.       { putc('\'', OutputFile);
  1097.       }
  1098.       putc('\n', OutputFile);
  1099.       OutputMode = OutputMode_None;
  1100.     }
  1101.     break;
  1102.       case TYPE_NONE:
  1103.     break;
  1104.     }
  1105. }
  1106.  
  1107.  
  1108.  
  1109.  
  1110. /*
  1111.     WriteBinChar writes one binary character into the source file
  1112. */
  1113. void WriteBinChar(int c)
  1114.  
  1115. {
  1116.   switch(OutputType)
  1117.   { case TYPE_C:
  1118.     case TYPE_OBERON:
  1119.       switch(c)
  1120.       { case '\b':
  1121.       fputs("\\b", OutputFile);
  1122.       break;
  1123.     case '\n':
  1124.       fputs("\\n", OutputFile);
  1125.       break;
  1126.     case '\r':
  1127.       fputs("\\r", OutputFile);
  1128.       break;
  1129.     case '\t':
  1130.       fputs("\\t", OutputFile);
  1131.       break;
  1132.     case '\f':
  1133.       fputs("\\f", OutputFile);
  1134.       break;
  1135.     case '\0':
  1136.       fputs("\\0", OutputFile);
  1137.       break;
  1138.     default:
  1139.       fprintf(OutputFile, "\\%c%c%c", ((c >> 6) & 3) + '0',
  1140.                   ((c >> 3) & 7) + '0', (c & 7) + '0');
  1141.       break;
  1142.       }
  1143.       ++OutputLen;
  1144.       OutputMode = OutputMode_Bin;
  1145.       break;
  1146.     case TYPE_ASSEMBLER:
  1147.       switch(OutputMode)
  1148.       { case OutputMode_None:
  1149.       fprintf(OutputFile, "\tdc.b\t$%02x", c & 0xff);
  1150.       break;
  1151.     case OutputMode_Ascii:
  1152.       putc('\'', OutputFile);
  1153.     case OutputMode_Bin:
  1154.       fprintf(OutputFile, ",$%02x", c & 0xff);
  1155.       break;
  1156.       }
  1157.       ++OutputLen;
  1158.       OutputMode = OutputMode_Bin;
  1159.       break;
  1160.     case TYPE_NONE:
  1161.       ShowWarn(GetFlexCatString(msgNoBinChars));
  1162.       break;
  1163.   }
  1164. }
  1165.  
  1166.  
  1167.  
  1168.  
  1169. /*
  1170.     WriteAsciiChar writes one ascii character into the source file.
  1171. */
  1172. void WriteAsciiChar(int c)
  1173.  
  1174. {
  1175.   switch(OutputType)
  1176.   { case TYPE_C:
  1177.     case TYPE_OBERON:
  1178.       switch(c)
  1179.       { case '\"':
  1180.       fputs("\\\"", OutputFile);
  1181.       break;
  1182.     default:
  1183.       putc(c, OutputFile);
  1184.       break;
  1185.       }
  1186.       ++OutputLen;
  1187.       OutputMode = OutputMode_Ascii;
  1188.       break;
  1189.     case TYPE_ASSEMBLER:
  1190.       if (c == '\'')
  1191.       { WriteBinChar(c);
  1192.       }
  1193.       else
  1194.       { switch (OutputMode)
  1195.     { case OutputMode_None:
  1196.         fprintf(OutputFile, "\tdc.b\t\'%c", c);
  1197.         break;
  1198.       case OutputMode_Ascii:
  1199.         putc(c, OutputFile);
  1200.         break;
  1201.       case OutputMode_Bin:
  1202.         fprintf(OutputFile, ",\'%c", c);
  1203.         break;
  1204.     }
  1205.     ++OutputLen;
  1206.     OutputMode = OutputMode_Ascii;
  1207.       }
  1208.       break;
  1209.     case TYPE_NONE:
  1210.       putc(c, OutputFile);
  1211.       break;
  1212.   }
  1213. }
  1214.  
  1215.  
  1216.  
  1217.  
  1218. /*
  1219.     TerminateCatStringOutput finishs the output of a catalog string.
  1220. */
  1221. void TerminateCatStringOutput(void)
  1222.  
  1223. {
  1224.   switch(OutputType)
  1225.   { case TYPE_C:
  1226.     case TYPE_OBERON:
  1227.       putc('\"', OutputFile);
  1228.       break;
  1229.     case TYPE_ASSEMBLER:
  1230.       switch(OutputMode)
  1231.       { case OutputMode_Ascii:
  1232.       putc('\'', OutputFile);
  1233.     case OutputMode_Bin:
  1234.       break;
  1235.     case OutputMode_None:
  1236.       break;
  1237.       }
  1238.     case TYPE_NONE:
  1239.       break;
  1240.   }
  1241. }
  1242.  
  1243.  
  1244.  
  1245.  
  1246. /*
  1247.     This writes a sourcestring.
  1248. */
  1249. void WriteString(FILE *fpout, char *str, long Len)
  1250.  
  1251. { char bytes[10];
  1252.   int bytesread;
  1253.  
  1254.   InitCatStringOutput(fpout);
  1255.   if (Len >= 0)
  1256.   { int i;
  1257.  
  1258.     for(i = LengthBytes;  i >= 1;  i--)
  1259.     { WriteBinChar((int) ((char *) &Len)[sizeof(Len)-i]);
  1260.     }
  1261.   }
  1262.   while (*str)
  1263.   { bytesread = ReadChar(&str, bytes);
  1264.     if (bytesread)
  1265.     { unsigned char c;
  1266.  
  1267.       c = bytes[bytesread-1];
  1268.       if ((c >= 0x20  &&  c < 0x7f)  ||  c >= 0xa0)
  1269.       { WriteAsciiChar((int) c);
  1270.       }
  1271.       else
  1272.       { WriteBinChar((int) c);
  1273.       }
  1274.     }
  1275.     else
  1276.     { SeparateCatStringOutput();
  1277.     }
  1278.   }
  1279.   TerminateCatStringOutput();
  1280. }
  1281.  
  1282.  
  1283.  
  1284.  
  1285. /*
  1286.     Finally the source creation.
  1287. */
  1288. void CreateSourceFile(char *SourceFile, char *TemplateFile)
  1289.  
  1290. { FILE *fpin, *fpout;
  1291.   char *line;
  1292.  
  1293.   if (!(fpin = fopen(TemplateFile, "r")))
  1294.   { ShowError(GetFlexCatString(msgNoSourceDescription), TemplateFile);
  1295.   }
  1296.   if (!(fpout = fopen(SourceFile, "w")))
  1297.   { ShowError(GetFlexCatString(msgNoSource), SourceFile);
  1298.   }
  1299.  
  1300.   while(!feof(fpin)  &&  (line = ReadLine(fpin, FALSE)))
  1301.   { struct CatString *cs;
  1302.     int NeedRepeat;
  1303.     char bytes[10];
  1304.     int bytesread;
  1305.  
  1306.     cs = FirstCatString;
  1307.     do
  1308.     { char *currentline = line;
  1309.       NeedRepeat = FALSE;
  1310.  
  1311.       if (*currentline == '#'  &&  *(++currentline) == '#')
  1312.       { ++currentline;
  1313.     OverSpace(¤tline);
  1314.     if (strnicmp(currentline, "stringtype", 10) == 0)
  1315.     { currentline += 10;
  1316.       OverSpace(¤tline);
  1317.       if (strnicmp(currentline, "c", 1) == 0)
  1318.       { OutputType = TYPE_C;
  1319.         ++currentline;
  1320.       }
  1321.       else if (strnicmp(currentline, "assembler", 9) == 0)
  1322.       { OutputType = TYPE_ASSEMBLER;
  1323.         currentline += 9;
  1324.       }
  1325.       else if (strnicmp(currentline, "oberon", 6) == 0)
  1326.       { OutputType = TYPE_OBERON;
  1327.         currentline += 6;
  1328.       }
  1329.       else if (strnicmp(currentline, "none", 4)  ==  0)
  1330.       { OutputType = TYPE_NONE;
  1331.         currentline += 4;
  1332.       }
  1333.       else
  1334.       { ShowWarn(GetFlexCatString(msgUnknownStringType));
  1335.         currentline += strlen(currentline);
  1336.       }
  1337.       OverSpace(¤tline);
  1338.       if (*currentline)
  1339.       { ShowWarn(GetFlexCatString(msgExtraCharacters));
  1340.       }
  1341.       continue;
  1342.     }
  1343.     else if (strnicmp(currentline, "shortstrings", 12) == 0)
  1344.     { currentline += 12;
  1345.       LongStrings = FALSE;
  1346.       OverSpace(¤tline);
  1347.       if (*currentline)
  1348.       { ShowWarn(GetFlexCatString(msgExtraCharacters));
  1349.       }
  1350.       continue;
  1351.     }
  1352.       }
  1353.  
  1354.       currentline = line;
  1355.       while(*currentline)
  1356.       { bytesread = ReadChar(¤tline, bytes);
  1357.     if (bytesread)
  1358.     { if (*bytes == '%')
  1359.       { switch(*(currentline++))
  1360.         { case 'b':
  1361.         fputs(BaseName, fpout);
  1362.         break;
  1363.           case 'n':
  1364.         fprintf(fpout, "%d", NumStrings);
  1365.         break;
  1366.           case 'v':
  1367.         fprintf(fpout, "%d", CatVersion);
  1368.         break;
  1369.           case 'l':
  1370.         WriteString(fpout, Language, -1);
  1371.         break;
  1372.           case 'i':
  1373.         NeedRepeat = TRUE;
  1374.         if (cs) fputs(cs->ID_Str, fpout);
  1375.         break;
  1376.           case 'd':
  1377.         NeedRepeat = TRUE;
  1378.         if (cs) fprintf(fpout, "%d", cs->ID);
  1379.         break;
  1380.           case 's':
  1381.         NeedRepeat = TRUE;
  1382.         if (cs)
  1383.         { char *idstr;
  1384.           unsigned long len;
  1385.  
  1386.           if (LengthBytes)
  1387.           { idstr = cs->CD_Str;
  1388.             while(*idstr)
  1389.             { bytesread = ReadChar(&idstr, bytes);
  1390.               if (bytesread)
  1391.               { ++len;
  1392.               }
  1393.             }
  1394.           }
  1395.           WriteString(fpout, cs->CD_Str, LengthBytes ? len : -1);
  1396.         }
  1397.         break;
  1398.           case '(':
  1399.         NeedRepeat = TRUE;
  1400.         while(*currentline  &&  *currentline != ')')
  1401.         { bytesread = ReadChar(¤tline, bytes);
  1402.           if (bytesread  &&  cs  &&  cs->Next)
  1403.           { putc((int) bytes[bytesread-1], fpout);
  1404.           }
  1405.         }
  1406.         if (!*currentline)
  1407.         { ShowWarn(GetFlexCatString(msgNoTerminateBracket));
  1408.         }
  1409.         else
  1410.         { ++currentline;
  1411.         }
  1412.         break;
  1413.           default:
  1414.         putc((int) *(currentline++), fpout);
  1415.         }
  1416.       }
  1417.       else
  1418.       { putc((int) bytes[bytesread-1], fpout);
  1419.       }
  1420.     }
  1421.       }
  1422.       putc('\n', fpout);
  1423.     }
  1424.     while(NeedRepeat  &&  cs  &&  (cs = cs->Next));
  1425.  
  1426.     free(line);
  1427.   }
  1428.  
  1429.   fclose(fpin);
  1430.   fclose(fpout);
  1431. }
  1432.  
  1433.  
  1434.  
  1435.  
  1436. /*
  1437.     The Usage function describes the programs calling syntax.
  1438. */
  1439. void Usage(void)
  1440.  
  1441. {
  1442.   fputs((char *) GetFlexCatString(msgUsage), stderr);
  1443.   Cleanup(5);
  1444. }
  1445.  
  1446. /*
  1447.     Finally the main function. Does nothing special except for scanning
  1448.     the arguments.
  1449. */
  1450. void main (int argc, char *argv [])
  1451.  
  1452. { char *cdfile, *ctfile, *newctfile, *catalog;
  1453.   char *source, *template;
  1454.   int i, assembler;
  1455.  
  1456.   if (argc == 0)    /*  Aztec's entry point for workbench programs  */
  1457.   { exit(5);
  1458.   }
  1459.  
  1460. #ifdef AMIGA
  1461.   LocaleBase = OpenLibrary((STRPTR) "locale.library", 38);
  1462.   OpenFlexCatCatalog(NULL, NULL);
  1463. #endif
  1464.  
  1465.   cdfile = ctfile = newctfile = catalog = NULL;
  1466.   assembler = FALSE;
  1467.  
  1468.   for (i = 1;  i < argc;  i++)
  1469.   { if (strnicmp (argv[i], "catalog=", 8) == 0)
  1470.     { catalog = argv[i] + 8;
  1471.     }
  1472.     else if (stricmp (argv[i], "catalog") == 0)
  1473.     { if (i+1 == argc)
  1474.       { Usage();
  1475.       }
  1476.       catalog = argv[++i];
  1477.     }
  1478.     else if (strnicmp (argv[i], "newctfile=", 10) == 0)
  1479.     { newctfile = argv[i] + 10;
  1480.     }
  1481.     else if (strnicmp (argv[i], "newctfile", 10) == 0)
  1482.     { if (i+1 == argc)
  1483.       { Usage();
  1484.       }
  1485.       newctfile = argv[++i];
  1486.     }
  1487.     else if (cdfile == NULL)
  1488.     { if (stricmp(argv[i], "?") == 0  ||  stricmp(argv[i], "-h") == 0  ||
  1489.       stricmp(argv[i], "help") == 0)
  1490.       { Usage();
  1491.       }
  1492.       if (!ScanCDFile(cdfile = argv[i]))
  1493.       { Cleanup(10);
  1494.       }
  1495.     }
  1496.     else if (index(argv[i], '='))
  1497.     { source = AllocString(argv[i]);
  1498.       *(template = index(source, '=')) = '\0';
  1499.       ++template;
  1500.  
  1501.       CreateSourceFile(source, template);
  1502.     }
  1503.     else
  1504.     { if (ctfile)
  1505.       { Usage();
  1506.       }
  1507.       ctfile = argv[i];
  1508.     }
  1509.   }
  1510.  
  1511.   if (ctfile)
  1512.   { if(!ScanCTFile(ctfile, newctfile ? TRUE : FALSE))
  1513.     { Cleanup(10);
  1514.     }
  1515.   }
  1516.   if (catalog)
  1517.   { if (!ctfile)
  1518.     { fprintf(stderr, (char *) GetFlexCatString(msgNoCTArgument));
  1519.       Usage();
  1520.     }
  1521.     CreateCat(catalog);
  1522.   }
  1523.   if (newctfile)
  1524.   { CreateCTFile(newctfile);
  1525.   }
  1526.  
  1527.   Cleanup(0);
  1528. }
  1529.  
  1530.  
  1531.  
  1532.  
  1533. /*
  1534.     Dice's entry point for workbench programs
  1535. */
  1536. void wbmain(struct WBStartup *wbmsg)
  1537.  
  1538. { exit(5);
  1539. }
  1540.